package com.yjhb.android.sbz.mvp;

import android.text.TextUtils;

import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.GsonBuilder;
import com.yjhb.android.sbz.App;
import com.yjhb.android.sbz.BuildConfig;
import com.yjhb.android.sbz.http.RequestException;
import com.yjhb.android.sbz.tool.DataSaveTool;
import com.jojo.android.zxlib.base.mvp.BasePresenter;
import com.jojo.android.zxlib.base.mvp.BaseView;
import com.jojo.android.zxlib.tool.ZxDeviceTool;
import com.jojo.android.zxlib.tool.ZxLogTool;

import java.io.IOException;
import java.net.Proxy;
import java.util.concurrent.TimeUnit;

import okhttp3.Headers;
import okhttp3.Interceptor;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Converter;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;

/**
 * 创建者 zx
 * 创建时间 2021/4/12 16:43
 */
public abstract class BasicsPresenter<V extends BaseView, API> extends BasePresenter<V, API> {

    private String host = null;

    public BasicsPresenter(V v) {
        super(v);
    }

    @Override
    protected String baseUrl() {
        if (TextUtils.isEmpty(host)) {
            host = DataSaveTool.getHost();
        }
        return host;
    }

    @Override
    protected Retrofit initRetrofit() {
        //声明日志类
        HttpLoggingInterceptor httpLoggingInterceptor = new HttpLoggingInterceptor();
        //设定日志级别
        httpLoggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
        //自定义OkHttpClient
        OkHttpClient.Builder builder = new OkHttpClient.Builder();
        //超时设置
        builder.callTimeout(20, TimeUnit.SECONDS)
                .connectTimeout(20, TimeUnit.SECONDS)
                .readTimeout(20, TimeUnit.SECONDS)
                .writeTimeout(20, TimeUnit.SECONDS)
                //失败后尝试重连
                .retryOnConnectionFailure(true)

                //添加拦截器
                .addNetworkInterceptor(chain -> {
                    Request request = chain.request();
                    Request.Builder requestBuilder = request.newBuilder();
                    if (App.userInfo != null && !TextUtils.isEmpty(App.UUID)) {
                        requestBuilder.addHeader("uuid", App.UUID);
                        ZxLogTool.i("UUID", App.UUID);
                    }
                    request = requestBuilder
                            //设备标识
                            .addHeader("device", "android")
                            //APP版本
                            .addHeader("version", ZxDeviceTool.getAppVersionName(App.getInstance()))
//                          .addHeader("Connection","close")
                            .build();
                    //请求结束后关闭连接
                    Response response = null;
                    try {
                        response = chain.proceed(request);
                    } catch (Exception e) {
                        //将异常信息上传至云端
                        StringBuilder tag = new StringBuilder("request");
                        tag.append(request.url().toString());
                        if (response != null) {
                            tag.append("\n");
                            tag.append("response:");
                            tag.append(response);
                        }
                        ZxLogTool.err(new RequestException(tag.toString(), e));
                        //抛出异常交给okHttp处理
                        throw e;
                    }
                    return response;
                })
                //自定义一个拦截器  打印请求头信息
                .addNetworkInterceptor(new Interceptor() {
                    @Override
                    public Response intercept(Chain chain) throws IOException {
                        Request request = chain.request();
                        Headers headers = request.headers();
                        for (int i = 0, count = headers.size(); i < count; i++) {
                            String name = headers.name(i);
                            // Skip headers from the request body as they are explicitly logged above.
//                            if (!"Content-Type".equalsIgnoreCase(name) && !"Content-Length".equalsIgnoreCase(name)) {
                            ZxLogTool.i("OkHttpHeader", name + ": " + headers.value(i));
//                            }
                        }
                        return chain.proceed(request);
                    }
                })
                .addInterceptor(httpLoggingInterceptor);
        //设置不允许代理
        if (!allowProxy() && !BuildConfig.DEBUG) {
            builder.proxy(Proxy.NO_PROXY);
        }
        return new Retrofit.Builder()
                .client(builder.build())
                .addConverterFactory(converterFactory())
                .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
                .baseUrl(baseUrl()).build();
    }

    /**
     * 是否允许代理
     *
     * @return
     */
    protected boolean allowProxy() {
        switch (baseUrl()) {
            case BuildConfig.ServerURL_TEST:
            case BuildConfig.ServerURL_ALPHA:
                return true;
            default:
                return false;
        }

    }

    /**
     * 默认的数据转化工厂
     *
     * @return
     */
    protected Converter.Factory converterFactory() {
        return GsonConverterFactory.
                create(new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss")
                        .addSerializationExclusionStrategy(new ExclusionStrategy() {
                            @Override
                            public boolean shouldSkipField(FieldAttributes f) {
                                return f.getName().equals("sId") ||
                                        f.getName().equals("dbId");
                            }

                            @Override
                            public boolean shouldSkipClass(Class<?> clazz) {
                                return false;
                            }
                        })
                        .create());
    }

}
